/*
 * TempDir.java
 *
 * Created on 26 December 2004, 04:53
 */

package org.owasp.webscarab.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import java.util.Random;
import java.security.AccessController;
import java.security.AccessControlException;
import sun.security.action.GetPropertyAction;

/**
 *
 * @author  rogan
 */
public class TempDir {
    
    /** Creates a new instance of TempDir */
    private TempDir() {
    }
    
    /* -- Temporary files -- */
    
    private static final Object tmpFileLock = new Object();
    
    private static int counter = -1; /* Protected by tmpFileLock */
    
    private static File generateFile(String prefix, String suffix, File dir) {
        if (counter == -1) {
            counter = new Random().nextInt() & 0xffff;
        }
        counter++;
        return new File(dir, prefix + Integer.toString(counter) + suffix);
    }
    
    private static String tmpdir; /* Protected by tmpFileLock */
    
    private static String getTempDir() {
        if (tmpdir == null) {
            GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");
            tmpdir = ((String) AccessController.doPrivileged(a));
        }
        return tmpdir;
    }
    
    private static boolean checkAndCreate(File file, SecurityManager sm) {
        if (sm != null) {
            try {
                sm.checkWrite(file.getPath());
            } catch (AccessControlException x) {
                /* Throwing the original AccessControlException could disclose
                   the location of the default temporary directory, so we
                   re-throw a more innocuous SecurityException */
                throw new SecurityException("Unable to create temporary file");
            }
        }
        if (file.exists()) return false;
        return file.mkdirs();
    }
    
    /**
     * <p> Creates a new directory in the specified directory, using the
     * given prefix and suffix strings to generate its name.  If this method
     * returns successfully then it is guaranteed that:
     *
     * <ol>
     * <li> The directory denoted by the returned abstract pathname did not exist
     *      before this method was invoked, and
     * <li> Neither this method nor any of its variants will return the same
     *      abstract pathname again in the current invocation of the virtual
     *      machine.
     * </ol>
     *
     * This method provides only part of a temporary-file facility.  To arrange
     * for a file created by this method to be deleted automatically, use the
     * <code>{@link #deleteOnExit}</code> method.
     *
     * <p> The <code>prefix</code> argument must be at least three characters
     * long.  It is recommended that the prefix be a short, meaningful string
     * such as <code>"hjb"</code> or <code>"mail"</code>.  The
     * <code>suffix</code> argument may be <code>null</code>, in which case the
     * suffix <code>".tmp"</code> will be used.
     *
     * <p> To create the new file, the prefix and the suffix may first be
     * adjusted to fit the limitations of the underlying platform.  If the
     * prefix is too long then it will be truncated, but its first three
     * characters will always be preserved.  If the suffix is too long then it
     * too will be truncated, but if it begins with a period character
     * (<code>'.'</code>) then the period and the first three characters
     * following it will always be preserved.  Once these adjustments have been
     * made the name of the new file will be generated by concatenating the
     * prefix, five or more internally-generated characters, and the suffix.
     *
     * <p> If the <code>directory</code> argument is <code>null</code> then the
     * system-dependent default temporary-file directory will be used.  The
     * default temporary-file directory is specified by the system property
     * <code>java.io.tmpdir</code>.  On UNIX systems the default value of this
     * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
     * Microsoft Windows systems it is typically <code>"c:\\temp"</code>.  A different
     * value may be given to this system property when the Java virtual machine
     * is invoked, but programmatic changes to this property are not guaranteed
     * to have any effect upon the the temporary directory used by this method.
     *
     * @param  prefix     The prefix string to be used in generating the file's
     *                    name; must be at least three characters long
     *
     * @param  suffix     The suffix string to be used in generating the file's
     *                    name; may be <code>null</code>, in which case the
     *                    suffix <code>".tmp"</code> will be used
     *
     * @param  directory  The directory in which the file is to be created, or
     *                    <code>null</code> if the default temporary-file
     *                    directory is to be used
     *
     * @return  An abstract pathname denoting a newly-created empty file
     *
     * @throws  IllegalArgumentException
     *          If the <code>prefix</code> argument contains fewer than three
     *          characters
     *
     * @throws  IOException  If a file could not be created
     *
     * @throws  SecurityException
     *          If a security manager exists and its <code>{@link
     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
     *          method does not allow a file to be created
     *
     * @since 1.2
     */
    public static File createTempDir(String prefix, String suffix,
            File directory) {
        if (prefix == null) throw new NullPointerException();
        if (prefix.length() < 3)
            throw new IllegalArgumentException("Prefix string too short");
        String s = (suffix == null) ? ".tmp" : suffix;
        synchronized (tmpFileLock) {
            if (directory == null) {
                directory = new File(getTempDir());
            }
            SecurityManager sm = System.getSecurityManager();
            File f;
            do {
                f = generateFile(prefix, s, directory);
            } while (!checkAndCreate(f, sm));
            return f;
        }
    }
    
    /**
     * Recursive delete files.
     */
    public static boolean recursiveDelete(File dir) {
        String[] ls = dir.list();
        
        for (int i = 0; i < ls.length; i++) {
            File file = new File(dir, ls[i]);
            if (file.isDirectory()) {
                if (!recursiveDelete(file)) return false;
            } else {
                if (!file.delete()) return false;
            }
        }
        return dir.delete();
    }
    
    public static void recursiveCopy(File source, File dest) throws IOException {
        if (dest.exists())
            throw new IOException("Directory already exists: " + dest);
        if (!source.isDirectory())
            throw new IOException("Source is not a directory " + source);
        if (!dest.mkdirs()) 
            throw new IOException("Could not create destination directory " + dest);
        
        File[] ls = source.listFiles();
        
        for (int i = 0; i < ls.length; i++) {
            if (ls[i].isDirectory()) {
                recursiveCopy(ls[i], new File(dest, ls[i].getName()));
            } else {
                File newDest = new File(dest, ls[i].getName());
                FileInputStream fis = new FileInputStream(ls[i]);
                FileOutputStream fos = new FileOutputStream(newDest);
                byte[] buff = new byte[1024];
                int got;
                while ((got=fis.read(buff))>0) {
                    fos.write(buff, 0, got);
                }
                fis.close();
                fos.close();
            }
        }
    }
    
    
}
